import http from 'http'

const register = Symbol('register')
const routes = Symbol('routes')
const callback = Symbol('callback')
const match = Symbol('match')
const handle = Symbol('handle')

class LikeExpress {
	constructor() {
		// 存放中间件的列表
		this[routes] = {
			all: [],
			get: [],
			post: [],
			put: [],
			patch: [],
			delete: []
		}
	}

	[register] = (path, ...middleware) => {
		const info = {}
		if (typeof path === 'string') {
			info.path = path
			// info.stack = slice.call(arguments, 1) // 从第二个参数开始, 转换为数组, 存入 stack
			info.stack = middleware
		} else {
			info.path = '/'
			// info.stack = slice.call(arguments, 0) // 从第一个参数开始, 转换为数组, 存入 stack
			info.stack = [path, ...middleware]
		}

		return info
	}

	use() {
		const info = this[register].apply(this, arguments)
		this[routes].all.push(info)
	}

	get() {
		const info = this[register].apply(this, arguments)
		this[routes].get.push(info)
	}

	post() {
		const info = this[register].apply(this, arguments)
		this[routes].post.push(info)
	}

	[match] = (method, url) => {
		const stack = []
		if (url === '/favicon.ico') {
			return stack
		}

		// 获取 routes
		const curRoutes = [...this[routes].all, ...this[routes][method]]

		curRoutes.forEach((routeInfo) => {
			if (url.indexOf(routeInfo.path) === 0) {
				stack.push(...routeInfo.stack)
			}
		})

		return stack
	};

	// next 机制的核心部分
	[handle] = (req, res, stack) => {
		const next = () => {
			// 拿到第一个匹配的中间件
			const middleware = stack.shift()
			if (middleware) {
				middleware(req, res, next)
			}
		}
		next()
	};

	[callback] = (req, res) => {
		res.json = (data) => {
			res.setHeader('Content-type', 'application/json')
			res.end(JSON.stringify(data))
		}
		const url = req.url
		const method = req.method.toLowerCase()
		const resultList = this[match](method, url)

		this[handle](req, res, resultList)
	}

	listen(...args) {
		const server = http.createServer(this[callback])
		server.listen(...args)
	}
}

// 工厂函数
export default function () {
	return new LikeExpress()
}
